using RuoYi.Data;
using RuoYi.Data.Dtos;
using RuoYi.Data.Entities;

namespace RuoYi.System.Repositories
{
    /// <summary>
    ///  菜单权限表 Repository
    ///  author ruoyi
    ///  date   2023-08-21 14:40:23
    /// </summary>
    public class SysMenuRepository : BaseRepository<SysMenu, SysMenuDto>
    {
        public SysMenuRepository(ISqlSugarRepository<SysMenu> sqlSugarRepository)
        {
            Repo = sqlSugarRepository;
        }

        public override ISugarQueryable<SysMenu> Queryable(SysMenuDto dto)
        {
            return Repo.AsQueryable()
                .WhereIF(!string.IsNullOrEmpty(dto.Status), (m) => m.Status == dto.Status)
                .WhereIF(!string.IsNullOrEmpty(dto.MenuName), (m) => m.MenuName!.Contains(dto.MenuName!))
                .WhereIF(!string.IsNullOrEmpty(dto.Visible), (m) => m.Visible == dto.Visible)
                .OrderBy(m => new { m.ParentId, m.OrderNum })
            ;
        }

        public override ISugarQueryable<SysMenuDto> DtoQueryable(SysMenuDto dto)
        {
            return Repo.AsQueryable()
                .LeftJoin<SysRoleMenu>((m, rm) => m.MenuId == rm.MenuId)
                .LeftJoin<SysUserRole>((m, rm, ur) => rm.RoleId == ur.RoleId)
                .LeftJoin<SysRole>((m, rm, ur, r) => rm.RoleId == r.RoleId)
                .WhereIF(!string.IsNullOrEmpty(dto.Status), (m, rm, ur, r) => m.Status == dto.Status)
                .WhereIF(!string.IsNullOrEmpty(dto.MenuName), (m, rm, ur, r) => m.MenuName!.Contains(dto.MenuName!))
                .WhereIF(!string.IsNullOrEmpty(dto.Visible), (m, rm, ur, r) => m.Visible == dto.Visible)
                .WhereIF(dto.UserId > 0, (m, rm, ur, r) => ur.UserId == dto.UserId)
                .WhereIF(dto.RoleId > 0, (m, rm, ur, r) => rm.RoleId == dto.RoleId)
                .WhereIF(!string.IsNullOrEmpty(dto.RoleStatus), (m, rm, ur, r) => r.Status == dto.RoleStatus)
                .OrderBy(m => new { m.ParentId, m.OrderNum })
                .Select((m, rm, ur, r) => new SysMenuDto
                {
                    CreateBy = m.CreateBy,
                    CreateTime = m.CreateTime,
                    UpdateBy = m.UpdateBy,
                    UpdateTime = m.UpdateTime,

                    MenuId = m.MenuId,
                    ParentId = m.ParentId,
                    MenuName = m.MenuName,
                    Path = m.Path,
                    Component = m.Component,
                    Query = m.Query,
                    Visible = m.Visible,
                    Status = m.Status,
                    Perms = m.Perms,
                    IsFrame = m.IsFrame,
                    IsCache = m.IsCache,
                    MenuType = m.MenuType,
                    Icon = m.Icon,
                    OrderNum = m.OrderNum,
                }).Distinct();
        }

        public async Task<List<SysMenu>> SelectMenuListAsync(SysMenuDto dto)
        {
            var entities = await this.GetListAsync(dto);
            return entities;
        }

        public async Task<List<SysMenuDto>> SelectMenuDtoListByUserIdAsync(SysMenuDto dto)
        {
            var dtos = await this.GetDtoListAsync(dto);
            return dtos;
        }

        public async Task<List<SysMenu>> SelectMenuListByUserIdAsync(SysMenuDto dto)
        {
            var dtos = await this.GetDtoListAsync(dto);
            return dtos.Adapt<List<SysMenu>>();
        }

        /// <summary>
        /// 根据用户ID查询菜单
        /// </summary>
        public List<string> SelectMenuPermsByUserId(long userId)
        {
            var query = new SysMenuDto { Status = Status.Enabled, UserId = userId };

            var dtos = this.GetDtoList(query);

            return dtos.Where(d => !string.IsNullOrEmpty(d.Perms)).Select(d => d.Perms).ToList()!;
        }

        /// <summary>
        /// 根据角色ID查询权限
        /// </summary>
        public List<string> SelectMenuPermsByRoleId(long roleId)
        {
            var query = new SysMenuDto { Status = Status.Enabled, RoleId = roleId };

            var dtos = this.GetDtoList(query);

            return dtos.Where(d => !string.IsNullOrEmpty(d.Perms)).Select(d => d.Perms).ToList()!;
        }

        /// <summary>
        /// 查询菜单
        /// </summary>
        public List<SysMenu> SelectMenuTreeAll()
        {
            var sql = @"
		        select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.`query`, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
		        from sys_menu m where m.menu_type in ('M', 'C') and m.status = 0
		        order by m.parent_id, m.order_num
            ";

            return base.SqlQueryable(sql).ToList();
        }

        /// <summary>
        /// 根据用户ID查询菜单
        /// </summary>
        public List<SysMenu> SelectMenuTreeByUserId(long userId)
        {
            //  var sql = @"
            //select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.`query`, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
            //from sys_menu m
            //left join sys_role_menu rm on m.menu_id = rm.menu_id
            //left join sys_user_role ur on rm.role_id = ur.role_id
            //left join sys_role ro on ur.role_id = ro.role_id
            //where ur.user_id = @UserId
            //  ";

            SysMenuDto dto = new SysMenuDto { UserId = userId, Status = Status.Enabled, RoleStatus = Status.Enabled };

            return this.GetList(dto);
        }

        public List<long> SelectMenuListByRoleId(long roleId, bool isMenuCheckStrictly)
        {
            var sql = @"
                select m.menu_id
		        from sys_menu m
                left join sys_role_menu rm on m.menu_id = rm.menu_id
                where rm.role_id = @RoleId
            ";
            if (isMenuCheckStrictly)
            {
                sql += "and m.menu_id not in (select m.parent_id from sys_menu m inner join sys_role_menu rm on m.menu_id = rm.menu_id and rm.role_id = @RoleId)";
            }
            sql += "order by m.parent_id, m.order_num";

            List<SugarParameter> parameters = new List<SugarParameter> {
                new SugarParameter("@RoleId" , roleId)
            };

            return base.SqlQueryable(sql, parameters)
                  .Select(m => m.MenuId)
                  .ToList();
        }


        public SysMenu SelectMenuById(long menuId)
        {
            return this.FirstOrDefault(m => m.MenuId == menuId);
        }

        public bool HasChildByMenuId(long parentId)
        {
            return this.Count(m => m.ParentId == parentId) > 0;
        }

        public SysMenu CheckMenuNameUnique(string menuName, long parentMenuId)
        {
            return this.FirstOrDefault(m => m.MenuName == menuName && m.ParentId == parentMenuId);
        }
    }
}